package com.bilibili.juc.spuriouswakeup;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 虚假唤醒  最开始未满足条件都在等待，结果没有明确条件 .signalAll()集体唤醒了所以等待的线程，解决办法是用while循环来让它再次判断
 * volatile 可以保证 有序性和可见性，但不能保证原子性，可见性就是修改了立马刷新到主内存，再通知其他线程读取
 */
class SpuriousWakeup {
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition hasApple = lock.newCondition();
    private static volatile int nApple;
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            lock.lock();
            try {
                if (nApple == 0) {
                    System.out.println(Thread.currentThread().getName()+":没苹果，我先休息会儿，苹果来了我再醒...");
                    hasApple.await(); //从哪里被唤醒就从哪里继续执行
                }
                nApple -= 1;
                System.out.println(Thread.currentThread().getName()+":哇，苹果来了，我吃掉了...");
                System.out.println(Thread.currentThread().getName()+":现在苹果还有 " + nApple + " 个...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "萧炎").start();
        new Thread(() -> {
            lock.lock();
            try {
                if (nApple == 0) {
                    System.out.println(Thread.currentThread().getName()+":没苹果，我先休息会儿，苹果来了我再醒...");
                    hasApple.await();
                }
                nApple -= 1;
                System.out.println(Thread.currentThread().getName()+":哇，苹果来了，我吃掉了...");
                System.out.println(Thread.currentThread().getName()+":现在苹果还有 " + nApple + " 个...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "唐三").start();

        Thread.sleep(1000);

        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+":我来送苹果了，但只有一个哦...");
                nApple = 1;
                hasApple.signalAll();
            } finally {
                lock.unlock();
            }
        }, "萧薰儿").start();
    }
}

